/*-------------------------------------------------
 *
 * OrbitsWriter - An Offline Blog Writer
 *
 * Copyright (C) 2016  devbean@galaxyworld.org
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *-------------------------------------------------*/

#include "appcontext.h"
#include "document/markupbuilder.h"
#include "mainwindow.h"
#include "plugin.h"
#include "pluginmanager.h"

#include <QDebug>

using namespace Core;
using namespace Core::Internal;

static AppContext *_INSTANCE = nullptr;

//---------- AppContextPrivate ----------//

AppContextPrivate::AppContextPrivate(AppContext *ctx)
    : QObject(ctx),
      q(ctx)
{
    connect(q, &AppContext::appContextStarted,
            this, &AppContextPrivate::onAppContextStarted);
    connect(q, &AppContext::appContextAboutToExit,
            this, &AppContextPrivate::onAppContextAboutToExit);
}

AppContextPrivate::~AppContextPrivate()
{
    QList<MarkupBuilderData *> data = builders.values();
    qDeleteAll(data);
    data.clear();

    builders.clear();

    delete mainWindow;
    delete pluginManager;
}

void AppContextPrivate::onAppContextStarted()
{
    readSettings();
}

void AppContextPrivate::onAppContextAboutToExit()
{
    writeSettings();
}

static const char * const GROUP_MAINWINDOW  = "MainWindow";
static const char * const SETTINGS_SIZE     = "size";
static const char * const SETTINGS_POSITION = "pos";

void AppContextPrivate::writeSettings()
{
    settings->beginGroup(QLatin1String(GROUP_MAINWINDOW));
    settings->setValue(QLatin1String(SETTINGS_SIZE), mainWindow->size());
    settings->setValue(QLatin1String(SETTINGS_POSITION), mainWindow->pos());
    settings->endGroup();
}

void AppContextPrivate::readSettings()
{
    settings->beginGroup(QLatin1String(GROUP_MAINWINDOW));
    mainWindow->resize(settings->value(QLatin1String(SETTINGS_SIZE), QSize(1024, 768)).toSize());
    mainWindow->move(settings->value(QLatin1String(SETTINGS_POSITION), QPoint(200, 200)).toPoint());
    settings->endGroup();
}

MarkupBuilderData::MarkupBuilderData()
    : highlighter(nullptr)
{

}

//---------- AppContext ----------//

AppContext *AppContext::instance()
{
    return _INSTANCE;
}

AppContext::AppContext(QObject *parent)
    : QObject(parent),
      d(new Internal::AppContextPrivate(this))
{
    _INSTANCE = this;

    d->pluginManager = new PluginManager;
    d->mainWindow = new MainWindow;
}

AppContext::~AppContext()
{
}

void AppContext::start()
{
    d->pluginManager->loadPlugins();
    qDebug() << "Plugins loaded.";

    emit appContextStarted();

    d->mainWindow->show();

    emit mainWindowShown();
}

void AppContext::shutdown()
{
    emit appContextAboutToExit();
}

void AppContext::setSettings(QSettings *settings)
{
    d->settings = settings;
    if (d->settings) {
        d->settings->setParent(d);
    }
}

QSettings *AppContext::settings() const
{
    return d->settings;
}

MainWindow * AppContext::mainWindow() const
{
    return d->mainWindow;
}

PluginManager * AppContext::pluginManager() const
{
    return d->pluginManager;
}

void AppContext::registerBuilder(MarkupBuilder *builder)
{
    d->builders.insert(builder, new Internal::MarkupBuilderData);
}

void AppContext::registerSyntaxHighlighter(MarkupBuilder *builder, QSyntaxHighlighter *highlighter)
{
    Internal::MarkupBuilderData *data = d->builders.value(builder, nullptr);
    if (!data) {
        registerBuilder(builder);
        data = d->builders.value(builder);
    }
    data->highlighter = highlighter;
}

QList<MarkupBuilder *> AppContext::builders() const
{
    return d->builders.keys();
}

QSyntaxHighlighter *AppContext::highlighter(MarkupBuilder *builder) const
{
    return d->builders.value(builder)->highlighter;
}
